# coding=utf8
# prosta baza danych, z api jak w Google Appengine
# po prostu zapisuje wszystko w YAML-u do pliku
# po każdym zapisie
# docelowo powinien to być binding do mongodb
import yaml
import os
import collections
import base64

_db = collections.defaultdict(dict)
_db_filename = 'dev_db.yaml'
try:
    _db.update(yaml.load(open(_db_filename)))
except IOError:
    print('dev_db not loaded')

def _flush_db():
    data = yaml.dump(dict(_db))
    with open(_db_filename, 'w') as f:
        f.write(data)

class Model(object):
    def __init__(self, name, fields):
        self._name = name
        self._fields = fields.split()
        self._data = {}
    
    def __call__(self, **kwargs):
        m = ModelInstance(self)
        for k, v in kwargs.items():
            setattr(m, k, v)
        return m
    
    def get_by_id(self, id):
        m = ModelInstance(self)
        m._id = id
        for k, v in _db[self._name][id].items():
            setattr(m, k, v)
        return m
    
    def all(self):
        return [ self.get_by_id(id) for id in _db[self._name].keys() ]

class ModelInstance(object):
    def __init__(self, model):
        self.model = model
        self._id = None
    
    @property
    def id(self):
        if self._id is None:
            raise ValueError('id not yet initialized')
        return self._id
    
    def to_dict(self):
        return {
            name: getattr(self, name, None)
            for name in self.model._fields
        }
    
    def put(self):
        data = self.to_dict()
        if not self._id:
            self._id = base64.urlsafe_b64encode(os.urandom(12)).decode('ascii')
        _db[self.model._name][self._id] = data
        _flush_db()
    
    def delete(self):
        del _db[self.model._name][self.id]
        self._id = None
        _flush_db()
    